﻿using CatUtils.Utils.Currency;
using CatUtils.Utils.Currency.IoUtils;
using ImageMagick;
using System;
using System.IO;

namespace AndoridMoeTool.AndroidTool.SDK.Media
{
    /// <summary>
    /// 图像处理帮助类
    /// </summary>
    public class MagickImageHelper
    {/// <summary>
     /// 图像高斯模糊
     /// </summary>
     /// <param name="ImgPath"></param>
     /// <param name="Radius">模糊半径</param>
     /// <param name="Sigma">模糊值</param>
     /// <param name="Tip">请在这里写子文件夹名字，默认为空（覆盖）</param>
     /// <returns></returns>
        public string ImgBlur(string ImgPath, int Radius = 10, int Sigma = 15, string Tip = "")
        {
            string ChildPath = "";
            using (MagickImage image = new MagickImage(ImgPath))
            {
                image.Blur(Radius, Sigma);
                ChildPath = MagickImageWrite(ImgPath, image, Tip);
            }

            return ChildPath;
        }

        /// <summary>
        /// 图像百分比剪裁
        /// </summary>
        /// <param name="ImgPath"></param>
        /// <param name="WidthPercentage"></param>
        /// <param name="HeightPercentage"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgCrop(string ImgPath, double WidthPercentage, double HeightPercentage, string Tip = "")
        {
            string ChildPath = "";
            WidthPercentage = WidthPercentage * 0.01;
            HeightPercentage = HeightPercentage * 0.01;
            using (MagickImage image = new MagickImage(ImgPath))
            {
                Console.WriteLine((int)(image.Height * HeightPercentage));
                Console.WriteLine(image.Height * HeightPercentage);
                image.Crop((int)(image.Width * WidthPercentage), (int)(image.Height * HeightPercentage));
                ChildPath = MagickImageWrite(ImgPath, image, Tip);
            }
            return ChildPath;
        }

        /// <summary>
        /// 将图片合并到指定位置
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="CompositeFile"></param>
        /// <param name="gravity"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImageComposite(string FilePath, string CompositeFile, Gravity gravity, string Tip = "图片合并")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    using (MagickImage CompositeImage = new MagickImage(CompositeFile))
                    {
                        image.Composite(CompositeImage, gravity);
                        return MagickImageWrite(CompositeFile, image, Tip);
                    }
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }
            return "";
        }

        /// <summary>
        /// 根据指定的宽高调整图片大小
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="Width"></param>
        /// <param name="Height"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgResize(String FilePath, int Width, int Height, string Tip = "指定宽高")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    MagickGeometry size = new MagickGeometry(Width, Width);

                    image.Resize(size);

                    // Save the result
                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }

            return "";
        }

        /// <summary>
        /// 根据指定的宽高调整图片大小
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="percentage"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgResize(String FilePath, Percentage percentage, string Tip = "百分比")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    // This will resize the image to a fixed size without maintaining the aspect ratio.
                    // Normally an image will be resized to fit inside the specified size.

                    image.Resize(percentage);

                    // Save the result
                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }
            return "";
        }

        /// <summary>
        /// 根据指定的宽高调整图片大小
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="percentageWidth"></param>
        /// <param name="percentageHeight"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgResize(String FilePath, Percentage percentageWidth, Percentage percentageHeight, string Tip = "百分比")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    // This will resize the image to a fixed size without maintaining the aspect ratio.
                    // Normally an image will be resized to fit inside the specified size.

                    image.Resize(percentageWidth, percentageHeight);

                    // Save the result
                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }

            return "";
        }

        /// <summary>
        /// 写入文件
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="image"></param>
        /// <param name="Tip">请在这里写子文件夹名字，默认为空（覆盖）</param>
        private string MagickImageWrite(string FilePath, MagickImage image, string Tip = "")
        {
            String SaveFloder = "";
            if (Tip == "")
                SaveFloder = FloderNameHelper.GetFloderPath(FilePath);
            else
                SaveFloder = FloderNameHelper.CreateChildFloderPath(FloderNameHelper.GetFloderPath(FilePath), Tip, true);

            SaveFloder = SaveFloder + Path.GetFileName(FilePath);
            try
            {
                image.Write(SaveFloder);
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }

            return SaveFloder;
        }

        /// <summary>
        /// 无损压缩并且覆盖
        /// </summary>
        /// <param name="FilePath"></param>
        /// <returns></returns>
        public bool CompressImg(String FilePath)
        {
            if (FilePath == "")
                return false;

            try
            {
                FileInfo snakewareLogo = new FileInfo(FilePath);
                ImageOptimizer optimizer = new ImageOptimizer();

                optimizer.LosslessCompress(snakewareLogo);

                snakewareLogo.Refresh();
            }
            catch (Exception ex)
            {
                PrintLog.E(ex);
            }
            return true;
        }

        /// <summary>
        /// 图片二值化
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="PercentageCount"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgThreshold(string FilePath, int PercentageCount, string Tip = "二值化")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    image.Threshold(new Percentage(PercentageCount));

                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }

            return "";
        }

        /// <summary>
        /// 图片颜色反转并且灰度化
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="OnlyGrayScale"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgNegateGray(string FilePath, bool OnlyGrayScale = false, string Tip = "灰度化")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    image.Negate(OnlyGrayScale);

                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }
            return "";
        }

        /// <summary>
        /// 图片灰度化
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgGray(string FilePath, string Tip = "灰度化")
        {
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {//convert logo.png -threshold -1
                    image.Grayscale(new PixelIntensityMethod());

                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex) { PrintLog.Log(ex); }
            return "";
        }

        /// <summary>
        /// 缩放到指定大小
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="ReSizeTo"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ImgResizeToFileSize(String FilePath, int ReSizeTo, string Tip = "缩放压缩")
        {
            if (FilePath == "")
                return "";
            double FileSize = FileHelper.GetFileSizeForKB(FilePath);
            string TempFilePath = FilePath;
            double Percentage = GetNewPercentage(FileSize, ReSizeTo, 100);
            try
            {
                if (FileSize < ReSizeTo || Percentage <= 1)
                {
                    TempFilePath = FileNameHelper.CreateFileNameWithChildFloder(FilePath, Tip);

                    FileHelper.FileCopy(FilePath, TempFilePath, true);
                    Console.WriteLine("无需压缩");

                    return TempFilePath;
                }

                //计算方法运行时间
                System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();

                stopwatch.Start();

                while (true)
                {
                    TempFilePath = ResizeWithPercentage(Percentage, Percentage, FilePath, Tip);
                    FileSize = FileHelper.GetFileSizeForKB(TempFilePath);
                    Percentage = GetNewPercentage(FileSize, ReSizeTo, Percentage);
                    Console.WriteLine($"本次压缩参数{Percentage}%,负数为通过区间判定：运行{stopwatch.Elapsed.TotalSeconds}秒");

                    if ((int)Math.Ceiling(Percentage) < 1 || stopwatch.Elapsed.TotalSeconds > 600)
                    {
                        return TempFilePath;
                    }
                    if (TempFilePath != FilePath)
                    {
                        Console.WriteLine("删除缓存文件：" + TempFilePath);
                        FileHelper.FileDelete(TempFilePath);
                    }
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }

            return TempFilePath;
        }

        /// <summary>
        /// 获取一个新的百分比指示
        /// </summary>
        /// <param name="TempFileSize"></param>
        /// <param name="ReSizeTo"></param>
        /// <param name="Percentage"></param>
        /// <returns></returns>
        private double GetNewPercentage(double TempFileSize, int ReSizeTo, double Percentage)
        {
            double Multiple = Math.Round(TempFileSize / ReSizeTo, 3);
            Console.WriteLine("现有大小{0}是目标{1}的{2}倍。上次使用比例参数：{3}", TempFileSize, ReSizeTo, Multiple, Percentage);
            double TempPercentage = Percentage;
            if (Multiple >= 10)
            {
                TempPercentage = Percentage * 0.3;
            }
            else if (Multiple >= 3)
            {
                TempPercentage = Percentage * 0.5;
            }
            else if (Multiple >= 2)
            {
                TempPercentage = Percentage * 0.7;
            }
            else if (Multiple >= 1.5)
                TempPercentage = Percentage * 0.93;
            else if (Multiple >= 1.2)
                TempPercentage = Percentage * 0.94;
            else if (Multiple <= 1.19 && Multiple >= 0.90)//如果在这个区间直接结束判断
                TempPercentage = -1;
            else if (Multiple >= 0.01)
                TempPercentage = Percentage * 1.11;

            return TempPercentage;
        }

        /// <summary>
        /// 质量压缩模式 不缩放图片
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="PercentageCount"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string CompressImgForQuality(String FilePath, int PercentageCount, string Tip = "不缩放压缩")
        {
            string ChildPath = "";
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    image.Quality = PercentageCount;

                    ChildPath = MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.E(ex);
            }
            return ChildPath;
        }

        /// <summary>
        /// 剪裁通过高度，起始点x0y0，高度自行设定百分比，为清理水印用
        /// </summary>
        /// <param name="FilePath"></param>
        /// <param name="PercentageCount"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string CorpImgWithHeight(String FilePath, int PercentageCount = 90, string Tip = "不缩放压缩")
        {
            string ChildPath = "";
            try
            {
                using (MagickImage image = new MagickImage(FilePath))
                {
                    int TempHeight = (int)(image.Height * (PercentageCount * 0.01));
                    image.Crop(new MagickGeometry(0, 0, image.Width, TempHeight), Gravity.Undefined);

                    ChildPath = MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex) { PrintLog.Log(ex); }

            return ChildPath;
        }

        /// <summary>
        /// 根据百分比压缩调整图片
        /// </summary>
        /// <param name="PercentageWidth"></param>
        /// <param name="PercentageHeight"></param>
        /// <param name="FilePath"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ResizeWithPercentage(double PercentageWidth, double PercentageHeight, string FilePath, string Tip = "百分比压缩")
        {
            return ResizeWithPercentage(new MagickGeometry(new Percentage(PercentageWidth), new Percentage(PercentageHeight)), FilePath, Tip);
        }

        /// <summary>
        /// 根据百分比压缩调整图片
        /// </summary>
        /// <param name="PercentageWidth"></param>
        /// <param name="PercentageHeight"></param>
        /// <param name="FilePath"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ResizeWithPercentage(int PercentageWidth, int PercentageHeight, string FilePath, string Tip = "百分比压缩")
        {
            return ResizeWithPercentage(new MagickGeometry(new Percentage(PercentageWidth), new Percentage(PercentageHeight)), FilePath, Tip);
        }

        /// <summary>
        /// 根据百分比压缩调整图片
        /// </summary>
        /// <param name="percentage"></param>
        /// <param name="FilePath"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ResizeWithPercentage(MagickGeometry percentage, string FilePath, string Tip = "百分比压缩")
        {
            return ResizeWithPercentage(percentage, new MagickImage(FilePath), FilePath, Tip);
        }

        /// <summary>
        /// 根据百分比压缩调整图片
        /// </summary>
        /// <param name="percentage"></param>
        /// <param name="image"></param>
        /// <param name="FilePath"></param>
        /// <param name="Tip"></param>
        /// <returns></returns>
        public string ResizeWithPercentage(MagickGeometry percentage, MagickImage image, string FilePath, string Tip = "百分比压缩")
        {
            try
            {
                using (image)
                {
                    if (percentage.Width <= 0 || percentage.Height <= 0)
                    {
                        PrintLog.E($"图片宽高出现问题，宽度比例为：{ percentage.Width }，高度比例为：{ percentage.Height }");
                        return MagickImageWrite(FilePath, image, Tip);
                    }

                    image.Resize(percentage);

                    // Save the result
                    return MagickImageWrite(FilePath, image, Tip);
                }
            }
            catch (Exception ex)
            {
                PrintLog.Log(ex);
            }
            return FilePath;
        }
    }
}